package main

import (
	"fmt"
	"io"
	"strconv"
	"time"

	"net"
	"sync"

	"github.com/axgle/mahonia"
)

type Server struct {
	Ip        string
	Port      int
	OnlineMap map[string]*User
	mapLock   sync.RWMutex
	Message   chan string
}

func NewServer(ip string, port int) *Server {
	server := &Server{
		Ip:        ip,
		Port:      port,
		OnlineMap: make(map[string]*User),
		Message:   make(chan string),
	}
	return server
}

// 广播用户上线消息
func (this *Server) BroadCast(user *User, msg string) {
	sendMsg := "[" + user.Addr + "]" + user.Name + ":" + msg
	this.Message <- sendMsg
}

// 发送全部用户消息通
func (this *Server) ListenMessage() {
	for {
		msg := <-this.Message
		this.mapLock.Lock()
		for _, cli := range this.OnlineMap {
			cli.C <- msg
		}
		this.mapLock.Unlock()
	}
}

func (this *Server) ConvertGB(msg string) string {
	enc := mahonia.NewEncoder("gbk")
	lastmsg := enc.ConvertString(msg)
	return lastmsg
}

func (this *Server) Hanlder(conn net.Conn) {
	fmt.Println("connected")
	user := NewUser(conn, this)

	//广播消息

	user.Online()
	//检测用户在线channel
	isLive := make(chan bool)
	//接收客户端发送
	go func() {
		buf := make([]byte, 4096)

		for {
			n, err := conn.Read(buf)
			fmt.Println("info:" + strconv.Itoa(n))
			if n == 0 {
				user.Offline()
				return
			}
			if err != nil && err != io.EOF {
				fmt.Println("conn read err:", err)
				return
			}

			msg := string(buf[:n])
			user.DoMessage(msg)
		}
	}()
	//select
	select {
	case <-isLive:
	case <-time.After(time.Second * 1000):
		user.SendMsg(this.ConvertGB("你被下线了"))
		close(user.C)
		conn.Close()
		return
	}
}
func (this *Server) Start() {
	Listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", this.Ip, this.Port))
	if err != nil {
		fmt.Println("listen err:", err)
	}
	defer Listener.Close()
	go this.ListenMessage()
	for {

		conn, err := Listener.Accept()
		if err != nil {
			fmt.Println("Listener accept err:", err)
			continue
		}
		//do conn
		go this.Hanlder(conn)
	}

}
